package com.mi.baselibrary.widget.chatline

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.Rect
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
import java.text.DecimalFormat
import kotlin.math.floor
import kotlin.math.log10
import kotlin.math.pow
import kotlin.math.roundToInt

/**
 * 折线图
 */
class LineChart : View{
    private var options = ChartOptions()

    /**
     * X轴相关
     */
    private val xAxisTextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)

    private val xAxisLinePaint = Paint(Paint.ANTI_ALIAS_FLAG)

    private val xAxisTexts = mutableListOf<String>()

    private var xAxisHeight = 0f

    /**
     * Y轴相关
     */

    private val yAxisTextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)

    private val yAxisLinePaint = Paint(Paint.ANTI_ALIAS_FLAG)

    private val yAxisTexts = mutableListOf<String>()

    private var yAxisWidth = 0f

    private var yAxisCount= 5

    private var yAxisMaxValue:Int=0

    /**
     * 原点
     */
    private var originX = 0f

    private var originY = 0f

    private var xGap =0f

    private var yGap=0f

    /**
     * 数据相关
     */
    private val pathPaint = Paint(Paint.ANTI_ALIAS_FLAG).also {
        it.style=Paint.Style.STROKE
    }

    private val ciclePaint = Paint(Paint.ANTI_ALIAS_FLAG).also {
        it.color=Color.parseColor("#79EBCF")
        it.style=Paint.Style.FILL
    }

    private val points = mutableListOf<ChartBean>()

    private val bounds = Rect()

    private val path = Path()

    constructor(context:Context)
              :this(context,null)

    constructor(context: Context, attrs: AttributeSet?)
              :this(context,attrs,0)

    constructor(context: Context,attrs: AttributeSet?,defStyleAttr:Int)
               :super(context,attrs,defStyleAttr)

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if(points.isEmpty()) return
        val xAxisOptions=options.xAxisOptions
        val yAxisOptions=options.yAxisOptions
        val dataOptions=options.dataOptions
        //设置原点
        originX=yAxisWidth
        originY=height - xAxisHeight
        //设置X轴Y轴间隔
        xGap=(width-originX)/points.size
        //Y轴默认顶部会留出一半空间
        yGap=originY/(yAxisCount-1+0.5f)
        //绘制X轴
        if(xAxisOptions.isEnableLine){
            xAxisLinePaint.strokeWidth=xAxisOptions.lineWidth
            xAxisLinePaint.color=xAxisOptions.lineColor
            xAxisLinePaint.pathEffect=xAxisOptions.linePathEffect
            canvas.drawLine(originX,originY,width.toFloat(),originY,xAxisLinePaint)
        }
        xAxisTexts.forEachIndexed { index, text ->
            val pointX = originX + index * xGap
            //刻度线
            if(xAxisOptions.isEnableRuler){
                xAxisLinePaint.strokeWidth = xAxisOptions.rulerWidth
                xAxisLinePaint.color = xAxisOptions.rulerColor
                canvas.drawLine(pivotX,originY,
                    pointX,originY-xAxisOptions.rulerHeight,
                    xAxisLinePaint)
            }
            //网格线
            if(xAxisOptions.isEnableGrid){
                xAxisLinePaint.strokeWidth=xAxisOptions.gridWidth
                xAxisLinePaint.color=xAxisOptions.gridColor
                xAxisLinePaint.pathEffect=xAxisOptions.gridPathEffect
                canvas.drawLine(pointX,originY,pointX,0f,xAxisLinePaint)
            }
            //文本
            bounds.setEmpty()
            xAxisTextPaint.textSize = xAxisOptions.textSize
            xAxisTextPaint.color = xAxisOptions.textColor
            xAxisTextPaint.getTextBounds(text,0,text.length,bounds)
            val fm = xAxisTextPaint.fontMetrics
            val fontHeight = fm.bottom - fm.top
            val fontX = originX + index*xGap +(xGap - bounds.width())/2f
            val fontBaseLine = originY + (xAxisHeight-fontHeight)/2f-fm.top
            canvas.drawText(text,fontX,fontBaseLine,xAxisTextPaint)
        }
        //绘制Y轴
        if(yAxisOptions.isEnableLine){
            yAxisLinePaint.strokeWidth= yAxisOptions.lineWidth
            yAxisLinePaint.color= yAxisOptions.lineColor
            yAxisLinePaint.pathEffect=yAxisOptions.linePathEffect
            canvas.drawLine(originY,0f,originX,originY,yAxisLinePaint)
        }
        yAxisTexts.forEachIndexed { index, text ->
            //刻度线
            val pointY = originY - index*yGap
            if(yAxisOptions.isEnableRuler){
                yAxisLinePaint.strokeWidth = yAxisOptions.rulerWidth
                yAxisLinePaint.color = yAxisOptions.rulerColor
                canvas.drawLine(originX,originY,
                    originX+yAxisOptions.rulerHeight,pointY,
                    yAxisLinePaint)
            }
            //网格线
            if(yAxisOptions.isEnableGrid){
                yAxisLinePaint.strokeWidth = yAxisOptions.gridWidth
                yAxisLinePaint.color = yAxisOptions.gridColor
                yAxisLinePaint.pathEffect = yAxisOptions.gridPathEffect
                canvas.drawLine(originX,pointY,width.toFloat(),pointY,yAxisLinePaint)
            }
            //文本
            bounds.setEmpty()
            yAxisTextPaint.textSize =yAxisOptions.textSize
            yAxisTextPaint.color = yAxisOptions.textColor
            yAxisTextPaint.getTextBounds(text,0,text.length,bounds)
            val fm = yAxisLinePaint.fontMetrics
            val x=(yAxisWidth-bounds.width())/2f
            val fontHeight = fm.bottom -fm.top
            val y=originY - index*yGap -fontHeight/2f -fm.top
            canvas.drawText(text,x,y,yAxisTextPaint)
        }
        //绘制数据
        path.reset()
        points.forEachIndexed { index, point ->
            val x=originX + index*xGap+xGap/2f
            val y=originY-(point.yAxis.toFloat()/yAxisMaxValue)*(yGap*(yAxisCount-1))
            if(index==0){
                path.moveTo(x,y)
            }else{
                path.lineTo(x,y)
            }
            //圆点
            ciclePaint.color=dataOptions.circleColor
            canvas.drawCircle(x,y,dataOptions.circleRadius,ciclePaint)
        }
        pathPaint.strokeWidth =dataOptions.pathWidth
        pathPaint.color =dataOptions.pathColor
        canvas.drawPath(path,pathPaint)
    }

    /**
     * 设置数据
     */
    fun setData(list:List<ChartBean>){
        points.clear()
        points.addAll(list)
        //设置X轴,Y轴数据
    }

    /**
     * 设置X轴数据
     */
    private fun setXAxisData(list:List<ChartBean>){
        val xAxisOptions = options.xAxisOptions
        val values = list.map { it.xAxis }
        //X轴文本
        xAxisTexts.clear()
        xAxisTexts.addAll(values)
        //X轴高度
        val fontMetrics = xAxisTextPaint.fontMetrics
        val lineHeight = fontMetrics.bottom - fontMetrics.top
         xAxisHeight=lineHeight+xAxisOptions.textMarginTop+xAxisOptions.textMarginBottom
    }

    /**
     * 设置Y轴数据
     */
    private fun setYAxisData(list:List<ChartBean>){
        val yAxisOptions = options.yAxisOptions
        yAxisTextPaint.textSize = yAxisOptions.textSize
        yAxisTextPaint.color = yAxisOptions.textColor
        val texts = list.map { it.yAxis.toString() }
        yAxisTexts.clear()
        yAxisTexts.addAll(texts)
        //Y轴高度
        val maxTextWidth = yAxisTexts.maxOf { yAxisTextPaint.measureText(it) }
        yAxisWidth = maxTextWidth + yAxisOptions.textMarginLeft + yAxisOptions.textMarginRight
        //Y轴间隔
        val maxY = list.maxOf {  it.yAxis }
        val interval = when{
            maxY<=10 -> getYInterval(10)
            else -> getYInterval(maxY)
        }
        //Y轴文字
        yAxisTexts.clear()
        for(index in 0..yAxisCount){
            val vaule = index*interval
            yAxisTexts.add(formatNum(vaule))
        }
        yAxisMaxValue = (yAxisCount-1)*interval
    }


    /**
     * 格式化数值
     */
    private fun formatNum(num:Int):String{
        val absNum = Math.abs(num)
        return  if(absNum>=0 && absNum<1000){
            return  num.toString()
        }else{
            val format = DecimalFormat("0.0")
            val value = num/1000f
            "${format.format(value)}k"
        }
    }

    /**
     * 根据Y轴最大值，数据获取Y轴的标准间隔
     */
    private fun getYInterval(maxY:Int):Int{
        val yIntervalCount = yAxisCount -1
        val rawInterval = maxY / yIntervalCount.toFloat()
        val magicPower = floor(log10(rawInterval.toDouble()))
        var magic = 10.0.pow(magicPower).toFloat()
        if(magic == rawInterval){
            magic = rawInterval
        }else{
            magic *= 10
        }
        val rawStandardInterval= rawInterval / magic
        val standardInterval = getStandardInterval(rawStandardInterval) * magic
        return standardInterval.roundToInt()
    }
    /**
     * 根据初始的间隔，转化为目标的间隔
     */
    private fun getStandardInterval(x:Float):Float{
        return  when{
            x<=0.1f -> 0.1f
            x<0.2f -> 0.2f
            x<=0.25f -> 0.25f
            x<=0.5f ->0.5f
            x<=1f ->1f
            else ->getStandardInterval(x/10)*10
        }
    }
    /**
     * 重置参数
     */
    fun setOptions(newOpions:ChartOptions){
        this.options=newOpions
        setData(points)
    }

    fun getOptions():ChartOptions{
        return  options
    }

    data class ChartBean(val xAxis:String, val yAxis:Int)

}